/**
 * 身份证号验证工具
 */

// 身份证号验证
export function validateIdCard(idCard: string): boolean {
  // 去除空格
  const id = idCard.trim()

  // 18位身份证号正则
  const reg18 = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/
  // 15位身份证号正则
  const reg15 = /^[1-9]\d{5}\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}$/

  if (!reg18.test(id) && !reg15.test(id)) {
    return false
  }

  // 18位身份证需要验证最后一位校验位
  if (id.length === 18) {
    return validateCheckCode(id)
  }

  return true
}

// 验证18位身份证的校验码
function validateCheckCode(idCard: string): boolean {
  const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']

  let sum = 0
  for (let i = 0; i < 17; i++) {
    sum += Number.parseInt(idCard[i], 10) * factor[i]
  }

  const checkCode = parity[sum % 11]
  return checkCode === idCard[17].toUpperCase()
}

// 隐藏身份证号中间部分
export function maskIdCard(idCard: string): string {
  if (!idCard || idCard.length < 8) {
    return idCard
  }

  // 显示前3位和后4位，中间用*代替
  const start = idCard.substring(0, 3)
  const end = idCard.substring(idCard.length - 4)
  const middle = '*'.repeat(idCard.length - 7)

  return `${start}${middle}${end}`
}

// 从身份证号中提取出生日期
export function getBirthFromIdCard(idCard: string): string | null {
  if (!idCard) return null

  let birthStr = ''
  if (idCard.length === 18) {
    birthStr = idCard.substring(6, 14)
  } else if (idCard.length === 15) {
    birthStr = `19${idCard.substring(6, 12)}`
  } else {
    return null
  }

  const year = birthStr.substring(0, 4)
  const month = birthStr.substring(4, 6)
  const day = birthStr.substring(6, 8)

  return `${year}-${month}-${day}`
}

// 从身份证号中提取性别
export function getGenderFromIdCard(idCard: string): '男' | '女' | null {
  if (!idCard) return null

  let genderCode = ''
  if (idCard.length === 18) {
    genderCode = idCard.substring(16, 17)
  } else if (idCard.length === 15) {
    genderCode = idCard.substring(14, 15)
  } else {
    return null
  }

  return Number.parseInt(genderCode, 10) % 2 === 0 ? '女' : '男'
}
